﻿//    HexagonMine
//    Copyright (c) 2009-2010 BenBear
//
//    This program is free software: you can redistribute it and/or modify
//    it under the terms of the GNU General Public License as published by
//    the Free Software Foundation, either version 3 of the License, or
//    (at your option) any later version.
//
//    This program is distributed in the hope that it will be useful,
//    but WITHOUT ANY WARRANTY; without even the implied warranty of
//    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
//    GNU General Public License for more details.
//
//    You should have received a copy of the GNU General Public License
//    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#include <mzfc_inc.h>
#include <string>
using std::wstring;

#include "HexagonMineConfigWnd.h"
#include "HexagonMineCanvas.h"

#include "HexagonMineGame.h"

#define     MZ_IDC_HM_CANVAS      100
#define     MZ_IDC_HM_TOOLBAR     101

#define     IDC_MENU_RESTART      151
#define     IDC_MENU_OPTION       152
#define     IDC_MENU_ABOUT        153
#define     IDC_MENU_RETURN       154
#define     IDC_MENU_DETECT       155

#define		TIMER_ID_OPERATE		1

class CHexagonMineWnd:public CMzWndEx, public hexagon_mine::IGameObserver
{
public:
	UiCaption m_Caption;
    CHexagonMineCanvas m_Canvas;
	UiToolbar_Text m_Toolbar;

	UiStatic m_Remain;
	UiStatic m_Opened;
	UiStatic m_Finish;

private:
	hexagon_mine::CHexagonMineGame m_Game;

	bool m_IsPlaying;

	int m_DownHexagonX;
	int m_DownHexagonY;
	DWORD m_DownTick;

	bool m_IsDetecting;

protected:
    virtual BOOL OnInitDialog()
    {
        if (!CMzWndEx::OnInitDialog())
        {
            return FALSE;
        }

		m_Caption.SetPos(0, 0, GetWidth(), MZM_HEIGHT_CAPTION);
		m_Caption.SetText(L"蜂窝扫雷");
		AddUiWin(&m_Caption);

        RECT rc = MzGetClientRect();

        m_Canvas.SetID(MZ_IDC_HM_CANVAS);
		m_Canvas.EnableNotifyMessage(true);
		m_Canvas.SetPos(0, MZM_HEIGHT_CAPTION, GetWidth(), GetHeight() - MZM_HEIGHT_TEXT_TOOLBAR - MZM_HEIGHT_SINGLELINE_EDIT - MZM_HEIGHT_CAPTION);
		m_Canvas.Init(&m_Game);

        AddUiWin(&m_Canvas);

	    m_Toolbar.SetPos(0, GetHeight() - MZM_HEIGHT_TEXT_TOOLBAR, GetWidth(), MZM_HEIGHT_TEXT_TOOLBAR);
		m_Toolbar.SetButton(0, true, true, L"退出");
		//m_Toolbar.EnableLeftArrow(true);
		m_Toolbar.SetButton(1, true, false, L"长按标雷");
		m_Toolbar.SetButton(2, true, true, L"菜单");
		m_Toolbar.SetID(MZ_IDC_HM_TOOLBAR);
		AddUiWin(&m_Toolbar);

		int remain_top = GetHeight() - MZM_HEIGHT_TEXT_TOOLBAR - MZM_HEIGHT_SINGLELINE_EDIT;
		m_Remain.SetPos(0, remain_top, GetWidth() / 2, MZM_HEIGHT_SINGLELINE_EDIT);
		m_Remain.SetDrawTextFormat(DT_CENTER | DT_VCENTER);
		AddUiWin(&m_Remain);

		m_Opened.SetPos(GetWidth() / 2, remain_top, GetWidth() / 2, MZM_HEIGHT_SINGLELINE_EDIT);
		m_Opened.SetDrawTextFormat(DT_CENTER | DT_VCENTER);
		AddUiWin(&m_Opened);

		m_Finish.SetPos(0, remain_top, GetWidth(), MZM_HEIGHT_SINGLELINE_EDIT);
		m_Finish.SetVisible(false);
		m_Finish.SetDrawTextFormat(DT_CENTER | DT_VCENTER);
		m_Finish.SetTextSize(MZM_HEIGHT_SINGLELINE_EDIT - 10);
		AddUiWin(&m_Finish);

		::srand(GetTickCount());

		m_Game.Register(this);
		m_Game.Register(&m_Canvas);

		m_Game.Start();

		m_IsPlaying = true;

		m_DownHexagonX = -1;
		m_DownHexagonY = -1;
		m_DownTick = 0;

		m_IsDetecting = false;

        return TRUE;
    }

    virtual void OnMzCommand(WPARAM wParam, LPARAM lParam)
    {
        UINT_PTR id = LOWORD(wParam);
        switch(id)
        {
		case MZ_IDC_HM_TOOLBAR:
			{
		        int nIndex = lParam;
				if (nIndex == 0)
				{
					PostQuitMessage(0);
					return;
				}
				else if (nIndex == 1)
				{
					if (!m_IsPlaying)
					{
						m_Remain.SetVisible(true);
						m_Remain.Invalidate();
						m_Opened.SetVisible(true);
						m_Opened.Invalidate();
						m_Finish.SetVisible(false);
						m_Finish.Invalidate();
					}

					m_Toolbar.SetButton(1, true, false, L"长按标雷");
					m_Toolbar.Invalidate();

					m_IsPlaying = true;
					m_IsDetecting = false;

					m_Game.Start();
				}
				else if (nIndex == 2)
				{
					DoMenu(ShowHexagonMenu());
				}
			}
			break;
		case MZ_IDC_HM_CANVAS:
			{
		        int x = LOWORD(lParam);
		        int y = HIWORD(lParam);

				int nNotify = wParam;

				CanvasMouseNotify(x, y, nNotify);
			}
			break;
		default:
			break;
		}
	}

	void CanvasMouseNotify(int x, int y, int nNotify)
	{
		int hx, hy;
		bool in_hole = m_Canvas.ConvertXYToHexagon(x, y, hx, hy);
		int op = m_Game.QueryOperation(hx, hy);

		switch (nNotify)
		{
		case MZ_MN_LBUTTONDOWN:
			{
				if (in_hole && (op != 0))
				{
					m_DownHexagonX = hx;
					m_DownHexagonY = hy;
					m_DownTick = GetTickCount();

					SetTimer(m_hWnd, TIMER_ID_OPERATE, 200, 0);

					m_Canvas.SetDownHexagonXY(hx, hy);
				}
			}
			break;
		case MZ_MN_LBUTTONUP:
			{
				if (m_DownHexagonX != -1)
				{
					if ((m_DownHexagonX == hx) && (m_DownHexagonY == hy))
					{
						hexagon_mine::CHexagonMineGame::OPERATE_TYPE operation = (hexagon_mine::CHexagonMineGame::OPERATE_TYPE)0;

						DWORD t = GetTickCount() - m_DownTick;
						if (t < 200)
						{
							if (m_IsDetecting)
							{
								operation = hexagon_mine::CHexagonMineGame::HMGO_DETECT;
								DoMenu(IDC_MENU_DETECT);
							}
							else if (op & hexagon_mine::CHexagonMineGame::HMGO_DIG)
							{
								operation = hexagon_mine::CHexagonMineGame::HMGO_DIG;
							}
						}
						else
						{
							if (op & hexagon_mine::CHexagonMineGame::HMGO_MARK)
								operation = hexagon_mine::CHexagonMineGame::HMGO_MARK;
						}

						if (operation)
							m_Game.Operate(hx, hy, operation);
					}
				}

				m_DownHexagonX = -1;
				m_DownHexagonY = -1;
				m_DownTick = 0;

				KillTimer(m_hWnd, TIMER_ID_OPERATE);

				m_Canvas.SetDownHexagonXY(-1, -1);
			}
			break;
		}
    }

	// 重载 MZFC 的消息处理函数
	LRESULT MzDefWndProc(UINT message, WPARAM wParam, LPARAM lParam)
	{
		switch(message)
		{
		case MZ_WM_MOUSE_NOTIFY:
			{
			    int nID = LOWORD(wParam);
				int nNotify = HIWORD(wParam);
		        int x = LOWORD(lParam);
		        int y = HIWORD(lParam);

				if (nID == MZ_IDC_HM_CANVAS)
				{
					CanvasMouseNotify(x, y, nNotify);
					return 0;
				}
			}
			break;
		case WM_TIMER:
			{
				UINT id = wParam;
				switch (id)
				{
				case TIMER_ID_OPERATE:
					{
						m_Canvas.UpdateDownHole();
					}
					break;
				}
			}
			break;
		}

		return CMzWndEx::MzDefWndProc(message, wParam, lParam);
	}

	int ShowHexagonMenu()
	{
		// 弹出菜单
		CPopupMenu ppm;
		struct PopupMenuItemProp pmip;      

		pmip.itemCr = MZC_BUTTON_PELLUCID;
		pmip.itemRetID = IDC_MENU_RETURN;
		pmip.str = L"返回";
		ppm.AddItem(pmip);

		if (m_IsPlaying && m_Game.HasDetector())
		{
			pmip.itemCr = MZC_BUTTON_PELLUCID;
			pmip.itemRetID = IDC_MENU_DETECT;
			if (m_IsDetecting == false)
				pmip.str = L"使用探测针";
			else
				pmip.str = L"放弃使用探测针";
			ppm.AddItem(pmip);
		}

		pmip.itemCr = MZC_BUTTON_PELLUCID;
		pmip.itemRetID = IDC_MENU_RESTART;
		if (m_IsPlaying)
			pmip.str = L"重新开始游戏";
		else
			pmip.str = L"开始游戏";
		ppm.AddItem(pmip);

		pmip.itemCr = MZC_BUTTON_ORANGE;
		pmip.itemRetID = IDC_MENU_OPTION;
		pmip.str = L"设置...";
		ppm.AddItem(pmip);

		pmip.itemCr = MZC_BUTTON_PELLUCID;
		pmip.itemRetID = IDC_MENU_ABOUT;
		pmip.str = L"关于蜂窝扫雷";
		ppm.AddItem(pmip);

		RECT rc = MzGetWorkArea();      
		rc.top = rc.bottom - ppm.GetHeight();
		ppm.Create(rc.left,rc.top,RECT_WIDTH(rc),RECT_HEIGHT(rc),m_hWnd,0,WS_POPUP);
		int nID = ppm.DoModal();
		return nID;
	}

	void DoMenu(int nID)
	{
		switch (nID)
		{
		case IDC_MENU_RESTART:
			{
				PostCommandMessage(MZ_IDC_HM_TOOLBAR, 0, 1);
			}
			break;
		case IDC_MENU_OPTION:
			{
				CHexagonMineConfigWnd dlg(&m_Game);
				RECT rcWork = MzGetWorkArea();
				dlg.Create(rcWork.left, rcWork.top, RECT_WIDTH(rcWork), RECT_HEIGHT(rcWork),
					m_hWnd, 0, WS_POPUP);
				// 设置窗口切换动画（弹出时的动画）
				dlg.SetAnimateType_Show(MZ_ANIMTYPE_SCROLL_BOTTOM_TO_TOP_2);
				// 设置窗口切换动画（结束时的动画）
				dlg.SetAnimateType_Hide(MZ_ANIMTYPE_SCROLL_TOP_TO_BOTTOM_1);
				int nRet = dlg.DoModal();
				if (nRet == ID_OK)
				{
					m_Game.SetConfig(dlg.GetConfig());
					PostCommandMessage(MZ_IDC_HM_TOOLBAR, 0, 1);
				}
			}
			break;
		case IDC_MENU_ABOUT:
			{
				MzMessageBoxEx(m_hWnd, L"\n蜂窝扫雷 0.9.4.3\nCopyright (c) 2009-2010 BenBear\n", L"蜂窝扫雷");
			}
			break;
		case IDC_MENU_RETURN:
			{
				return;
			}
			break;
		case IDC_MENU_DETECT:
			{
				m_IsDetecting = !m_IsDetecting;
				if (m_IsDetecting)
				{
					m_Toolbar.SetButton(1, true, false, L"探测模式");
					m_Toolbar.Invalidate();
				}
				else
				{
					m_Toolbar.SetButton(1, true, false, L"长按标雷");
					m_Toolbar.Invalidate();
				}
			}
			break;
		}
	}

protected:
	virtual void Info(const hexagon_mine::GameInfo& info)
	{
		wchar_t buf[32];
		swprintf(buf, L"剩余雷标：%d/%d", info.RemainMines, info.TotalMines);
		m_Remain.SetText(buf);
		m_Remain.Invalidate();

		swprintf(buf, L"已打开：%d/%d", info.OpenHoles, info.TotalHoles - info.TotalMines);
		m_Opened.SetText(buf);
		m_Opened.Invalidate();
	}

	virtual void Finish(bool win)
	{
		m_IsPlaying = false;

		if (win)
		{
			m_Finish.SetText(L"恭喜过关！");
			m_Finish.SetTextColor(RGB(0, 255, 0));
		}
		else
		{
			m_Finish.SetText(L"抱歉，您牺牲了！");
			m_Finish.SetTextColor(RGB(255, 0, 0));
		}

		m_Remain.SetVisible(false);
		m_Remain.Invalidate();
		m_Opened.SetVisible(false);
		m_Opened.Invalidate();

		m_Finish.SetVisible(true);
		m_Finish.Invalidate();

		m_Toolbar.SetButton(1, true, true, L"开始");
		m_Toolbar.Invalidate();
	}

private:
};

class CSampleApp: public CMzApp
{

public:
    //主窗体
    CHexagonMineWnd m_MainWnd;
    //初始化应用程序
    virtual BOOL Init()
    {
        CoInitializeEx(0, COINIT_MULTITHREADED);

        // 创建主窗体
        RECT rcWork = MzGetWorkArea();
        m_MainWnd.Create(rcWork.left,rcWork.top,RECT_WIDTH(rcWork),RECT_HEIGHT(rcWork), 0, 0, 0);
        m_MainWnd.SetBgColor(MzGetThemeColor(TCI_WINDOW_BG));
        m_MainWnd.Show();

        return TRUE;
    }
};

// 全局应用程序变量
CSampleApp theApp;
